<?php

declare(strict_types=1);

namespace EthanZ\HyperfExt\Exception\Handler;

use EthanZ\HyperfExt\Constants\Code;
use EthanZ\HyperfExt\Exception\BaseException;
use Hyperf\HttpMessage\Stream\SwooleStream;
use Hyperf\JsonRpc\DataFormatter;
use Hyperf\Logger\LoggerFactory;
use Hyperf\Rpc\Context;
use Hyperf\ExceptionHandler\ExceptionHandler;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Log\LoggerInterface;
use Throwable;

/**
 * 处理所有RPC服务异常.
 *
 * Class RpcExceptionHandler
 */
class RpcExceptionHandler extends ExceptionHandler
{

    /**
     * @var LoggerInterface
     */
    protected $logger;

    /**
     * @var BaseException
     */
    protected $response;

    /**
     * @var Code
     */
    protected $baseCode;

    public function __construct(BaseException $response, Code $baseCode, LoggerFactory $loggerFactory)
    {
        $this->response = $response;
        $this->baseCode = $baseCode;
        $this->logger   = $loggerFactory->get('log', 'default');
    }

    public function handle(Throwable $throwable, ?ResponseInterface $response)
    {
        // 记录日志.
        $exceptionContext = [
            'line'    => $throwable->getLine(),
            'file'    => $throwable->getFile(),
            'class'   => get_class($throwable),
            'code'    => $throwable->getCode(),
            'message' => $throwable->getMessage(),
        ];
        $this->logger->error($throwable->getMessage(), $exceptionContext);

        // 格式化输出.
        $data = json_encode(
            [
                'code'    => $throwable->getCode(),
                'message' => $throwable->getMessage(),
            ],
            JSON_UNESCAPED_UNICODE
        );
        $this->stopPropagation();

        return $response->withStatus(200)->withBody(new SwooleStream($data));
    }

    public function isValid(Throwable $throwable): bool
    {
        return true;
    }
}
